onilink_

4004 ROM Emulator

Aug 27th, 2021
1,299
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.71 KB | None | 0 0
  1.  
  2. MCS4::Chip4004::Chip4004(Circuit circuit_):
  3.     circuit(circuit_)
  4. {
  5.     circuit._list_out_map.resize(circuit._nodes.size());
  6.     circuit._group_map.resize(circuit._nodes.size());
  7.    
  8.     circuit.stabilizeChip();
  9.    
  10.     runInitSequence();
  11. }
  12.  
  13. void MCS4::Chip4004::coldReset()
  14. {
  15.     ComponentIndex index = 0;
  16.     for(auto& node: circuit._nodes) {
  17.         node.value = false;
  18.         circuit._list_out.push_back(index);
  19.         ++index;
  20.     }
  21.     for(auto& t: circuit._transistors) {
  22.         t.on = false;
  23.     }
  24.     circuit.stabilizeChip();
  25. }
  26.  
  27. void MCS4::Chip4004::runInitSequence()
  28. {
  29.     for(cycle=0; cycle<1100; ++cycle)
  30.     {
  31.         od::bitfield<16> bitset;
  32.         bitset[unsigned(Input::Clk1)] = (cycle+3) % 4 == 0;
  33.         bitset[unsigned(Input::Clk2)] = (cycle+1) % 4 == 0;
  34.         bitset[unsigned(Input::Sync)] = (cycle > 4)?(((cycle+32)/4)%8 == 0): 0;
  35.         bitset[unsigned(Input::Test)] = true;
  36.         bitset[unsigned(Input::Poc)]  = (cycle < 1099);
  37.        
  38.         for(unsigned i=0; i<circuit._inputs.size(); ++i) {
  39.             bool value = bitset[i];
  40.             circuit._nodes[circuit._inputs[i]].pullup = value;
  41.             circuit._nodes[circuit._inputs[i]].pulldown = !value;
  42.             circuit._list_out.push_back(circuit._inputs[i]);
  43.         }
  44.         circuit.recalcNodeList();
  45.     }
  46. }
  47.  
  48. bool MCS4::Chip4004::read(Input input) const
  49. {
  50.     return circuit._nodes.at(circuit._inputs.at(unsigned(input))).value;
  51. }
  52.  
  53. bool MCS4::Chip4004::read(Output output) const
  54. {
  55.     return circuit._nodes.at(circuit._outputs.at(unsigned(output))).value;
  56. }
  57.  
  58. MCS4::MCS4(Circuit circuit_):
  59.     chip_4004(circuit_)
  60. {
  61.     // init rom data
  62.     std::vector<uint8_t> temp = {
  63.         0x20, 0xFF, 0x22, 0xFF, 0x24, 0xFF,
  64.         0x26, 0xFF, 0x28, 0xFF, 0x2A, 0xFF,
  65.         0x2C, 0xFF, 0x2E, 0xFF};
  66.     setProgram(temp);
  67. }
  68.  
  69. void MCS4::setProgram(std::vector<uint8_t> program)
  70. {
  71.     roms.data.clear();
  72.     for(uint8_t b: program) {
  73.         roms.data.push_back((b>>4)&0xF);
  74.         roms.data.push_back(b&0xF);
  75.     }
  76. }
  77.  
  78. void MCS4::simulateOneClockPhase()
  79. {
  80.     auto& circuit = chip_4004.circuit;
  81.    
  82.     std::bitset<16> bitset, update;
  83.     cmrom  = chip_4004.read(Chip4004::Output::CM_Rom);
  84.     d0_pad = chip_4004.read(Chip4004::Input::D0);
  85.     d1_pad = chip_4004.read(Chip4004::Input::D1);
  86.     d2_pad = chip_4004.read(Chip4004::Input::D2);
  87.     d3_pad = chip_4004.read(Chip4004::Input::D3);
  88.    
  89.     updateSignals();
  90.     bitset = signals();
  91.     update = signalsToUpdate();
  92.    
  93.     for(unsigned i=0; i<circuit._inputs.size(); ++i) {
  94.         if(!update[i])
  95.         {
  96.             circuit._nodes[circuit._inputs[i]].pullup = false;
  97.             circuit._nodes[circuit._inputs[i]].pulldown = false;
  98.             circuit._list_out.push_back(circuit._inputs[i]);
  99.             continue;
  100.         }
  101.        
  102.         bool value = bitset[i];
  103.         circuit._nodes[circuit._inputs[i]].pullup = value;
  104.         circuit._nodes[circuit._inputs[i]].pulldown = !value;
  105.         circuit._list_out.push_back(circuit._inputs[i]);
  106.     }
  107.    
  108.     circuit.recalcNodeList();
  109. }
  110.  
  111. void MCS4::simulateOneInstructionCycle()
  112. {
  113.     for(unsigned i=0; i<32; ++i) {
  114.         simulateOneClockPhase();
  115.     }
  116. }
  117.  
  118. void MCS4::updateSignals() {
  119.     auto& cycle = chip_4004.cycle;
  120.     const bool pp_sync = (cycle > 4)?(((cycle+30)/4)%8 == 0): 0;
  121.     const bool p_sync  = (cycle > 4)?(((cycle+31)/4)%8 == 0): 0;
  122.    
  123.     clk1 = (cycle+3) % 4 == 0;
  124.     clk2 = (cycle+1) % 4 == 0;
  125.     sync = (cycle > 4)?(((cycle+32)/4)%8 == 0): 0;
  126.     test_pad = false;
  127.     poc_pad = false;
  128.    
  129.     if(cmrom_prev && !cmrom) {
  130.         d0_pad = d1_pad = d2_pad = d3_pad = true;
  131.         read_rom = true;
  132.         read_cycle = 0;
  133.     }
  134.     if(read_rom)
  135.     {
  136.         const unsigned rom_index = rom_cursor*2 + (read_cycle >= 4);
  137.         const uint8_t data = rom_index < roms.data.size()?
  138.                     roms.data[rom_index]: 0;
  139.        
  140.         d0_pad = (data >> 0) & 0x1;
  141.         d1_pad = (data >> 1) & 0x1;
  142.         d2_pad = (data >> 2) & 0x1;
  143.         d3_pad = (data >> 3) & 0x1;
  144.        
  145.         if(read_cycle == 10) {
  146.             read_rom = false;
  147.         }
  148.         else {
  149.             ++read_cycle;
  150.         }
  151.     }
  152.    
  153.     if(pp_sync && !p_sync) {
  154.         read_addr = true;
  155.         read_addr_cycle = 0;
  156.         rom_cursor = 0;
  157.     }
  158.    
  159.     if(read_addr) {
  160.         if(read_addr_cycle % 4 == 0) {
  161.             uint8_t w = 0;
  162.             w |= d0_pad << 0;
  163.             w |= d1_pad << 1;
  164.             w |= d2_pad << 2;
  165.             w |= d3_pad << 3;
  166.             rom_cursor = rom_cursor<<4 | w;
  167.             //std::cout << "w: " << int(w) << std::endl;
  168.             if(read_addr_cycle >= 8) {
  169.                 read_addr = false;
  170.                 rom_cursor =
  171.                         ((rom_cursor&0xF00)>>8) |
  172.                         (rom_cursor&0x0F0) |
  173.                         ((rom_cursor&0x00F)<<8);
  174.             }
  175.         }
  176.         ++read_addr_cycle;
  177.     }
  178.    
  179.     ++cycle;
  180.    
  181.     cmrom_prev = cmrom;
  182. }
  183.  
  184. std::bitset<16> MCS4::signals() const {
  185.     std::bitset<16> bitset;
  186.     bitset[0] = clk1;
  187.     bitset[1] = clk2;
  188.     bitset[2] = sync;
  189.    
  190.     if(read_rom) {
  191.         bitset[3] = d0_pad;
  192.         bitset[4] = d1_pad;
  193.         bitset[5] = d2_pad;
  194.         bitset[6] = d3_pad;
  195.     }
  196.    
  197.     bitset[7] = test_pad;
  198.     bitset[8] = poc_pad;
  199.    
  200.     return bitset;
  201. }
  202.  
  203. std::bitset<16> MCS4::signalsToUpdate() const {
  204.     std::bitset<16> bitset;
  205.     bitset[0] = true;
  206.     bitset[1] = true;
  207.     bitset[2] = true;
  208.    
  209.     if(read_rom) {
  210.         bitset[3] = true;
  211.         bitset[4] = true;
  212.         bitset[5] = true;
  213.         bitset[6] = true;
  214.     }
  215.     bitset[7] = true;
  216.     bitset[8] = true;
  217.     return bitset;
  218. }
  219.  
Advertisement
Add Comment
Please, Sign In to add comment