| // Copyright 2024 Google LLC |
| // Copyright lowRISC contributors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include <algorithm> |
| #include <iostream> |
| #include <string> |
| #include <vector> |
| |
| #include "verilated_toplevel.h" |
| #include "verilator_memutil.h" |
| #include "verilator_sim_ctrl.h" |
| |
| int main(int argc, char **argv) { |
| sencha_sim_tb top; |
| VerilatorMemUtil memutil; |
| VerilatorSimCtrl &simctrl = VerilatorSimCtrl::GetInstance(); |
| simctrl.SetTop(&top, &top.clk_i, &top.rst_ni, |
| VerilatorSimCtrlFlags::ResetPolarityNegative); |
| |
| std::string top_scope("TOP.sencha_sim_tb.u_dut.top_sencha"); |
| std::string ram1p_adv_scope( |
| "u_prim_ram_1p_adv.u_mem." |
| "gen_generic.u_impl_generic"); |
| |
| MemArea rom(top_scope + (".u_rom_ctrl.gen_rom_scramble_enabled.u_rom.u_rom." |
| "u_prim_rom.gen_generic.u_impl_generic"), |
| 0x4000 / 4, 4); |
| MemArea ram(top_scope + ".u_ram1p_ram_main." + ram1p_adv_scope, 0x20000 / 4, |
| 4); |
| // Only handle the lower bank of flash for now. |
| MemArea flash(top_scope + |
| ".u_flash_ctrl.u_eflash.u_flash.gen_generic.u_impl_generic." |
| "gen_prim_flash_banks[0].u_prim_flash_bank.u_mem." |
| "gen_generic.u_impl_generic", |
| 0x80000 / 8, 8); |
| // Start with the flash region erased. Future loads can overwrite. |
| std::vector<uint8_t> all_ones(flash.GetSizeBytes()); |
| std::fill(all_ones.begin(), all_ones.end(), 0xffu); |
| flash.Write(/*word_offset=*/0, all_ones); |
| |
| MemArea otp(top_scope + ".u_otp_ctrl.u_otp.gen_generic.u_impl_generic." + |
| ram1p_adv_scope, |
| 0x4000 / 4, 4); |
| MemArea ram_smc(top_scope + ".u_ram1p_ram_smc.u_mem.gen_generic.u_impl_generic", |
| 0x400000 / 4, 4); |
| MemArea ml_dmem(top_scope + ".u_ml_top.u_ml_dmem.u_ram1p_dmem.u_mem.gen_generic.u_impl_generic", |
| 0x400000 / 32, 32); |
| |
| memutil.RegisterMemoryArea("rom", 0x8000, &rom); |
| memutil.RegisterMemoryArea("ram", 0x10000000u, &ram); |
| memutil.RegisterMemoryArea("flash", 0x20000000u, &flash); |
| memutil.RegisterMemoryArea("otp", 0x40000000u /* (bogus LMA) */, &otp); |
| memutil.RegisterMemoryArea("ram_smc", 0x50000000u, &ram_smc); |
| memutil.RegisterMemoryArea("ml_dmem", 0x5A000000u, &ml_dmem); |
| simctrl.RegisterExtension(&memutil); |
| |
| // The initial reset delay must be long enough such that pwr/rst/clkmgr will |
| // release clocks to the entire design. This allows for synchronous resets |
| // to appropriately propagate. |
| // The reset duration must be appropriately sized to the divider for clk_aon |
| // in chip_sencha_verilator.sv. It must be at least 2 cycles of clk_aon. |
| simctrl.SetInitialResetDelay(20000); |
| simctrl.SetResetDuration(10); |
| |
| std::cout << "Simulation of Shodan Sencha" << std::endl |
| << "=================================" << std::endl |
| << std::endl; |
| |
| return simctrl.Exec(argc, argv).first; |
| } |