@@ -163,6 +163,60 @@ namespace eval _SC_INTERNALS {
163163 }
164164 sc_lib_print " [ sc_lib_write_reg mcountinhibit [format " 0x%08x" $inhibit_value ] ]"
165165 }
166+
167+ # # aarsize - data size: 2 (32 bits), 3 (64 bits), 4 (128 bits)
168+ proc sc_lib_get_aarsize {xlen} {
169+ if {$xlen == 32} {
170+ return 2
171+ }
172+ if {$xlen == 64} {
173+ return 3
174+ }
175+ return -code error " invalid MXL value: $xlen "
176+ }
177+
178+ proc sc_lib_riscv_encode_abstarct_command {regno write transfer aarsize cmdtype} {
179+ set cmd [expr {($regno & 0xFFFF) |
180+ ($write << 16) |
181+ ($transfer << 17) |
182+ ($aarsize << 20) |
183+ ($cmdtype << 24)}]
184+ return $cmd
185+ }
186+
187+ proc sc_lib_require_halted_and_check_csr {csr_num} {
188+ sc_lib_require_halted
189+ if {$csr_num > 4069 || $csr_num < 0} {
190+ return -code error " $csr_num is not a valid CSR number"
191+ }
192+ }
193+
194+ variable FPGA_LIB_BUSY_DURATION 3
195+
196+ proc sc_lib_riscv_csr_impl {csr_num value write xlen} {
197+ set aarsize [sc_lib_get_aarsize $xlen ]
198+ set COMMAND_ADDR 0x17
199+ riscv dmi_write $COMMAND_ADDR [sc_lib_riscv_encode_abstarct_command $csr_num \
200+ $write 1 $aarsize 0]
201+
202+ set ABSTRACTCS_ADDR 0x16
203+ set abstractcs [riscv dmi_read $ABSTRACTCS_ADDR ]
204+ set start_time [clock seconds]
205+
206+ while {$abstractcs & 0x1000 != 0} {
207+ if {([clock seconds] - $start_time ) >= [sc_fpga_get_busy_duration]} {
208+ return -code error " Busy bit set after duration time"
209+ }
210+ set abstractcs [riscv dmi_read $ABSTRACTCS_ADDR ]
211+ }
212+
213+ set cmderr [expr {($abstractcs & 0x700) >> 8}]
214+ if {$cmderr != 0} {
215+ riscv dmi_write $ABSTRACTCS_ADDR 0x700
216+ return -code error " problem with abstract command execution, \
217+ error code : $cmderr "
218+ }
219+ }
166220}
167221
168222proc sc_fpga_ctrl_silence {} {
@@ -301,6 +355,45 @@ proc sc_fpga_info {} {
301355 ] " \n " ]
302356}
303357
358+ proc sc_fpga_get_busy_duration {} {
359+ return ${::_SC_INTERNALS::FPGA_LIB_BUSY_DURATION}
360+ }
361+
362+ proc sc_fpga_set_busy_duration {value} {
363+ set ::_SC_INTERNALS::FPGA_LIB_BUSY_DURATION $value
364+ }
365+
366+ proc sc_fpga_riscv_csr_read {csr_num {xlen 64}} {
367+ _SC_INTERNALS::sc_lib_require_halted_and_check_csr $csr_num
368+
369+ _SC_INTERNALS::sc_lib_riscv_csr_impl $csr_num 0 0 $xlen
370+ set DATA_0 0x04
371+ set DATA_1 0x05
372+ if {$xlen == 32} {
373+ return [format 0x%.8x [expr {[riscv dmi_read $DATA_0 ]}]]
374+ }
375+ if {$xlen == 64} {
376+ return [format 0x%.16x [expr {[riscv dmi_read $DATA_0 ] | [riscv dmi_read $DATA_1 ]<<32}]]
377+ }
378+ return -code error " unsupported architecture size"
379+ }
380+
381+ proc sc_fpga_riscv_csr_write {csr_num value {xlen 64}} {
382+ _SC_INTERNALS::sc_lib_require_halted_and_check_csr $csr_num
383+
384+ set DATA_0 0x04
385+ set DATA_1 0x05
386+ if {$xlen == 32} {
387+ riscv dmi_write $DATA_0 $value
388+ }
389+ if {$xlen == 64} {
390+ riscv dmi_write $DATA_0 [expr {$value & 0xFFFFFFFF}]
391+ riscv dmi_write $DATA_1 [expr {$value >> 32}]
392+ }
393+
394+ _SC_INTERNALS::sc_lib_riscv_csr_impl $csr_num $value 1 $xlen
395+ }
396+
304397# # @return value of a counter corresponding to the specified event
305398# # @param[in] "context" object returned by sc_experimental_pmu_setup
306399# # @param[in] name of PMU event
0 commit comments