@ -31,16 +31,10 @@ static unsigned field_width(unsigned n)
///////////////////////// debug_module_t
debug_module_t : : debug_module_t ( sim_t * sim , unsigned progbufsize , unsigned max_bus_master_bits ,
bool require_authentication , unsigned abstract_rti , bool support_hasel ,
bool support_abstract_csr_access ) :
debug_module_t : : debug_module_t ( sim_t * sim , const debug_module_config_t & config ) :
nprocs ( sim - > nprocs ( ) ) ,
progbufsize ( progbufsize ) ,
program_buffer_bytes ( 4 + 4 * progbufsize ) ,
max_bus_master_bits ( max_bus_master_bits ) ,
require_authentication ( require_authentication ) ,
abstract_rti ( abstract_rti ) ,
support_abstract_csr_access ( support_abstract_csr_access ) ,
config ( config ) ,
program_buffer_bytes ( 4 + 4 * config . progbufsize ) ,
debug_progbuf_start ( debug_data_start - program_buffer_bytes ) ,
debug_abstract_start ( debug_progbuf_start - debug_abstract_size * 4 ) ,
custom_base ( 0 ) ,
@ -49,8 +43,7 @@ debug_module_t::debug_module_t(sim_t *sim, unsigned progbufsize, unsigned max_bu
// The spec lets a debugger select nonexistent harts. Create hart_state for
// them because I'm too lazy to add the code to just ignore accesses.
hart_state ( 1 < < field_width ( sim - > nprocs ( ) ) ) ,
hart_array_mask ( sim - > nprocs ( ) ) ,
support_hasel ( support_hasel )
hart_array_mask ( sim - > nprocs ( ) )
{
D ( fprintf ( stderr , " debug_data_start=0x%x \n " , debug_data_start ) ) ;
D ( fprintf ( stderr , " debug_progbuf_start=0x%x \n " , debug_progbuf_start ) ) ;
@ -62,10 +55,10 @@ debug_module_t::debug_module_t(sim_t *sim, unsigned progbufsize, unsigned max_bu
memset ( debug_rom_flags , 0 , sizeof ( debug_rom_flags ) ) ;
memset ( program_buffer , 0 , program_buffer_bytes ) ;
program_buffer [ 4 * progbufsize ] = ebreak ( ) ;
program_buffer [ 4 * progbufsize + 1 ] = ebreak ( ) > > 8 ;
program_buffer [ 4 * progbufsize + 2 ] = ebreak ( ) > > 16 ;
program_buffer [ 4 * progbufsize + 3 ] = ebreak ( ) > > 24 ;
program_buffer [ 4 * config . progbufsize ] = ebreak ( ) ;
program_buffer [ 4 * config . progbufsize + 1 ] = ebreak ( ) > > 8 ;
program_buffer [ 4 * config . progbufsize + 2 ] = ebreak ( ) > > 16 ;
program_buffer [ 4 * config . progbufsize + 3 ] = ebreak ( ) > > 24 ;
memset ( dmdata , 0 , sizeof ( dmdata ) ) ;
write32 ( debug_rom_whereto , 0 ,
@ -93,27 +86,27 @@ void debug_module_t::reset()
dmstatus = { 0 } ;
dmstatus . impebreak = true ;
dmstatus . authenticated = ! require_authentication ;
dmstatus . authenticated = ! config . require_authentication ;
dmstatus . version = 2 ;
abstractcs = { 0 } ;
abstractcs . datacount = sizeof ( dmdata ) / 4 ;
abstractcs . progbufsize = progbufsize ;
abstractcs . progbufsize = config . progbufsize ;
abstractauto = { 0 } ;
sbcs = { 0 } ;
if ( max_bus_master_bits > 0 ) {
if ( config . max_bus_master_bits > 0 ) {
sbcs . version = 1 ;
sbcs . asize = sizeof ( reg_t ) * 8 ;
}
if ( max_bus_master_bits > = 64 )
if ( config . max_bus_master_bits > = 64 )
sbcs . access64 = true ;
if ( max_bus_master_bits > = 32 )
if ( config . max_bus_master_bits > = 32 )
sbcs . access32 = true ;
if ( max_bus_master_bits > = 16 )
if ( config . max_bus_master_bits > = 16 )
sbcs . access16 = true ;
if ( max_bus_master_bits > = 8 )
if ( config . max_bus_master_bits > = 8 )
sbcs . access8 = true ;
challenge = random ( ) ;
@ -297,7 +290,7 @@ unsigned debug_module_t::sb_access_bits()
void debug_module_t : : sb_autoincrement ( )
{
if ( ! sbcs . autoincrement | | ! max_bus_master_bits )
if ( ! sbcs . autoincrement | | ! config . max_bus_master_bits )
return ;
uint64_t value = sbaddress [ 0 ] + sb_access_bits ( ) / 8 ;
@ -319,13 +312,13 @@ void debug_module_t::sb_read()
{
reg_t address = ( ( uint64_t ) sbaddress [ 1 ] < < 32 ) | sbaddress [ 0 ] ;
try {
if ( sbcs . sbaccess = = 0 & & max_bus_master_bits > = 8 ) {
if ( sbcs . sbaccess = = 0 & & config . max_bus_master_bits > = 8 ) {
sbdata [ 0 ] = sim - > debug_mmu - > load_uint8 ( address ) ;
} else if ( sbcs . sbaccess = = 1 & & max_bus_master_bits > = 16 ) {
} else if ( sbcs . sbaccess = = 1 & & config . max_bus_master_bits > = 16 ) {
sbdata [ 0 ] = sim - > debug_mmu - > load_uint16 ( address ) ;
} else if ( sbcs . sbaccess = = 2 & & max_bus_master_bits > = 32 ) {
} else if ( sbcs . sbaccess = = 2 & & config . max_bus_master_bits > = 32 ) {
sbdata [ 0 ] = sim - > debug_mmu - > load_uint32 ( address ) ;
} else if ( sbcs . sbaccess = = 3 & & max_bus_master_bits > = 64 ) {
} else if ( sbcs . sbaccess = = 3 & & config . max_bus_master_bits > = 64 ) {
uint64_t value = sim - > debug_mmu - > load_uint64 ( address ) ;
sbdata [ 0 ] = value ;
sbdata [ 1 ] = value > > 32 ;
@ -341,13 +334,13 @@ void debug_module_t::sb_write()
{
reg_t address = ( ( uint64_t ) sbaddress [ 1 ] < < 32 ) | sbaddress [ 0 ] ;
D ( fprintf ( stderr , " sb_write() 0x%x @ 0x%lx \n " , sbdata [ 0 ] , address ) ) ;
if ( sbcs . sbaccess = = 0 & & max_bus_master_bits > = 8 ) {
if ( sbcs . sbaccess = = 0 & & config . max_bus_master_bits > = 8 ) {
sim - > debug_mmu - > store_uint8 ( address , sbdata [ 0 ] ) ;
} else if ( sbcs . sbaccess = = 1 & & max_bus_master_bits > = 16 ) {
} else if ( sbcs . sbaccess = = 1 & & config . max_bus_master_bits > = 16 ) {
sim - > debug_mmu - > store_uint16 ( address , sbdata [ 0 ] ) ;
} else if ( sbcs . sbaccess = = 2 & & max_bus_master_bits > = 32 ) {
} else if ( sbcs . sbaccess = = 2 & & config . max_bus_master_bits > = 32 ) {
sim - > debug_mmu - > store_uint32 ( address , sbdata [ 0 ] ) ;
} else if ( sbcs . sbaccess = = 3 & & max_bus_master_bits > = 64 ) {
} else if ( sbcs . sbaccess = = 3 & & config . max_bus_master_bits > = 64 ) {
sim - > debug_mmu - > store_uint64 ( address ,
( ( ( uint64_t ) sbdata [ 1 ] ) < < 32 ) | sbdata [ 0 ] ) ;
} else {
@ -374,7 +367,7 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
if ( ! abstractcs . busy & & ( ( abstractauto . autoexecdata > > i ) & 1 ) ) {
perform_abstract_command ( ) ;
}
} else if ( address > = DMI_PROGBUF0 & & address < DMI_PROGBUF0 + progbufsize ) {
} else if ( address > = DMI_PROGBUF0 & & address < DMI_PROGBUF0 + config . progbufsize ) {
unsigned i = address - DMI_PROGBUF0 ;
result = read32 ( program_buffer , i ) ;
if ( abstractcs . busy ) {
@ -587,7 +580,7 @@ bool debug_module_t::perform_abstract_command()
unsigned i = 0 ;
if ( get_field ( command , AC_ACCESS_REGISTER_TRANSFER ) ) {
if ( regno < 0x1000 & & support_abstract_csr_access ) {
if ( regno < 0x1000 & & config . support_abstract_csr_access ) {
write32 ( debug_abstract , i + + , csrw ( S0 , CSR_DSCRATCH ) ) ;
if ( write ) {
@ -700,7 +693,7 @@ bool debug_module_t::perform_abstract_command()
}
debug_rom_flags [ dmcontrol . hartsel ] | = 1 < < DEBUG_ROM_FLAG_GO ;
rti_remaining = abstract_rti ;
rti_remaining = config . abstract_rti ;
abstract_command_completed = false ;
abstractcs . busy = true ;
@ -732,7 +725,7 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
}
return true ;
} else if ( address > = DMI_PROGBUF0 & & address < DMI_PROGBUF0 + progbufsize ) {
} else if ( address > = DMI_PROGBUF0 & & address < DMI_PROGBUF0 + config . progbufsize ) {
unsigned i = address - DMI_PROGBUF0 ;
if ( ! abstractcs . busy )
@ -757,7 +750,7 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
dmcontrol . resumereq = get_field ( value , DMI_DMCONTROL_RESUMEREQ ) ;
dmcontrol . hartreset = get_field ( value , DMI_DMCONTROL_HARTRESET ) ;
dmcontrol . ndmreset = get_field ( value , DMI_DMCONTROL_NDMRESET ) ;
if ( support_hasel )
if ( config . support_hasel )
dmcontrol . hasel = get_field ( value , DMI_DMCONTROL_HASEL ) ;
else
dmcontrol . hasel = 0 ;
@ -871,7 +864,7 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
case DMI_AUTHDATA :
D ( fprintf ( stderr , " debug authentication: got 0x%x; 0x%x unlocks \n " , value ,
challenge + secret ) ) ;
if ( require_authentication ) {
if ( config . require_authentication ) {
if ( value = = challenge + secret ) {
dmstatus . authenticated = true ;
} else {
@ -881,7 +874,7 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
}
return true ;
case DMI_DMCS2 :
if ( get_field ( value , DMI_DMCS2_HGWRITE ) ) {
if ( config . support_haltgroups & & get_field ( value , DMI_DMCS2_HGWRITE ) ) {
hart_state [ dmcontrol . hartsel ] . haltgroup = get_field ( value ,
DMI_DMCS2_HALTGROUP ) ;
}