Skip to content

Commit

Permalink
Merge branch 'master' into fix_rtd
Browse files Browse the repository at this point in the history
  • Loading branch information
duck2 authored May 9, 2023
2 parents e250076 + 3ecf1a3 commit 0b42593
Show file tree
Hide file tree
Showing 82 changed files with 4,031 additions and 3,479 deletions.
Binary file removed comparison_output.xlsx
Binary file not shown.
1 change: 1 addition & 0 deletions vpr/src/base/SetupVPR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ static void SetupPlacerOpts(const t_options& Options, t_placer_opts* PlacerOpts)
PlacerOpts->place_agent_epsilon = Options.place_agent_epsilon;
PlacerOpts->place_agent_gamma = Options.place_agent_gamma;
PlacerOpts->place_dm_rlim = Options.place_dm_rlim;
PlacerOpts->place_agent_space = Options.place_agent_space;
PlacerOpts->place_reward_fun = Options.place_reward_fun;
PlacerOpts->place_crit_limit = Options.place_crit_limit;
PlacerOpts->place_agent_algorithm = Options.place_agent_algorithm;
Expand Down
13 changes: 13 additions & 0 deletions vpr/src/base/clustered_netlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ t_logical_block_type_ptr ClusteredNetlist::block_type(const ClusterBlockId id) c
return block_types_[id];
}

std::vector<ClusterBlockId> ClusteredNetlist::blocks_per_type(const t_logical_block_type blk_type) const {
if (blocks_per_type_.count(blk_type.index) == 0) {
std::vector<ClusterBlockId> empty_vector;
return empty_vector;
}
return blocks_per_type_.at(blk_type.index);
}

ClusterNetId ClusteredNetlist::block_net(const ClusterBlockId blk_id, const int logical_pin_index) const {
auto pin_id = block_pin(blk_id, logical_pin_index);

Expand Down Expand Up @@ -108,6 +116,8 @@ ClusterBlockId ClusteredNetlist::create_block(const char* name, t_pb* pb, t_logi
block_pbs_.insert(blk_id, pb);
block_types_.insert(blk_id, type);

blocks_per_type_[type->index].push_back(blk_id);

//Allocate and initialize every potential pin of the block
block_logical_pins_.insert(blk_id, std::vector<ClusterPinId>(get_max_num_pins(type), ClusterPinId::INVALID()));
}
Expand Down Expand Up @@ -168,11 +178,14 @@ ClusterNetId ClusteredNetlist::create_net(const std::string name) {
}

void ClusteredNetlist::remove_block_impl(const ClusterBlockId blk_id) {
//find the block type, so we can remove it from blocks_per_type_ data structure
auto blk_type = block_type(blk_id);
//Remove & invalidate pointers
free_pb(block_pbs_[blk_id]);
delete block_pbs_[blk_id];
block_pbs_.insert(blk_id, NULL);
block_types_.insert(blk_id, NULL);
std::remove(blocks_per_type_[blk_type->index].begin(), blocks_per_type_[blk_type->index].end(), blk_id);
block_logical_pins_.insert(blk_id, std::vector<ClusterPinId>());
}

Expand Down
4 changes: 4 additions & 0 deletions vpr/src/base/clustered_netlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ class ClusteredNetlist : public Netlist<ClusterBlockId, ClusterPortId, ClusterPi
///@brief Returns the type of CLB (Logic block, RAM, DSP, etc.)
t_logical_block_type_ptr block_type(const ClusterBlockId id) const;

///@brief Returns the blocks with the specific block types in the netlist
std::vector<ClusterBlockId> blocks_per_type(const t_logical_block_type blk_type) const;

///@brief Returns the net of the block attached to the specific pin index
ClusterNetId block_net(const ClusterBlockId blk_id, const int pin_index) const;

Expand Down Expand Up @@ -331,6 +334,7 @@ class ClusteredNetlist : public Netlist<ClusterBlockId, ClusterPortId, ClusterPi
vtr::vector_map<ClusterBlockId, t_pb*> block_pbs_; ///<Physical block representing the clustering & internal hierarchy of each CLB
vtr::vector_map<ClusterBlockId, t_logical_block_type_ptr> block_types_; ///<The type of logical block this user circuit block is mapped to
vtr::vector_map<ClusterBlockId, std::vector<ClusterPinId>> block_logical_pins_; ///<The logical pin associated with each physical tile pin
std::unordered_map<int, std::vector<ClusterBlockId>> blocks_per_type_; ///<Block IDs associated with each physical block type, Used in placement to move specific block type

//Pins
/**
Expand Down
6 changes: 3 additions & 3 deletions vpr/src/base/netlist.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -977,12 +977,12 @@ void Netlist<BlockId, PortId, PinId, NetId>::remove_block(const BlockId blk_id)
StringId name_id = block_names_[blk_id];
block_name_to_block_id_.insert(name_id, BlockId::INVALID());

//Mark as invalid
block_ids_[blk_id] = BlockId::INVALID();

//Call derived class' remove()
remove_block_impl(blk_id);

//Mark as invalid
block_ids_[blk_id] = BlockId::INVALID();

//Mark netlist dirty
dirty_ = true;
}
Expand Down
39 changes: 39 additions & 0 deletions vpr/src/base/read_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,37 @@ struct ParsePlaceAgentAlgorithm {
}
};

struct ParsePlaceAgentSpace {
ConvertedValue<e_agent_space> from_str(std::string str) {
ConvertedValue<e_agent_space> conv_value;
if (str == "move_type")
conv_value.set_value(MOVE_TYPE);
else if (str == "move_block_type")
conv_value.set_value(MOVE_BLOCK_TYPE);
else {
std::stringstream msg;
msg << "Invalid conversion from '" << str << "' to e_agent_space (expected one of: " << argparse::join(default_choices(), ", ") << ")";
conv_value.set_error(msg.str());
}
return conv_value;
}

ConvertedValue<std::string> to_str(e_agent_space val) {
ConvertedValue<std::string> conv_value;
if (val == MOVE_TYPE)
conv_value.set_value("move_type");
else {
VTR_ASSERT(val == MOVE_BLOCK_TYPE);
conv_value.set_value("move_block_type");
}
return conv_value;
}

std::vector<std::string> default_choices() {
return {"move_type", "move_block_type"};
}
};

struct ParseFixPins {
ConvertedValue<e_pad_loc_type> from_str(std::string str) {
ConvertedValue<e_pad_loc_type> conv_value;
Expand Down Expand Up @@ -2083,6 +2114,14 @@ argparse::ArgumentParser create_arg_parser(std::string prog_name, t_options& arg
.choices({"e_greedy", "softmax"})
.show_in(argparse::ShowIn::HELP_ONLY);

place_grp.add_argument<e_agent_space, ParsePlaceAgentSpace>(args.place_agent_space, "--place_agent_space")
.help(
"Agent exploration space can be either based on only move types or also consider different block types\n"
"The available values are: move_type, move_block_type")
.default_value("move_block_type")
.choices({"move_type", "move_block_type"})
.show_in(argparse::ShowIn::HELP_ONLY);

auto& place_timing_grp = parser.add_argument_group("timing-driven placement options");

place_timing_grp.add_argument(args.PlaceTimingTradeoff, "--timing_tradeoff")
Expand Down
1 change: 1 addition & 0 deletions vpr/src/base/read_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct t_options {
argparse::ArgValue<float> place_agent_epsilon;
argparse::ArgValue<float> place_agent_gamma;
argparse::ArgValue<float> place_dm_rlim;
argparse::ArgValue<e_agent_space> place_agent_space;
argparse::ArgValue<e_agent_algorithm> place_agent_algorithm;
argparse::ArgValue<std::string> place_reward_fun;
argparse::ArgValue<float> place_crit_limit;
Expand Down
13 changes: 13 additions & 0 deletions vpr/src/base/vpr_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,19 @@ struct PlacementContext : public Context {
* Used for unique identification and consistency checking
*/
std::string placement_id;

/**
* @brief Map physical block type to RL-agent block type
*
* RL-agent block types are the physical block types that are used in the netlist (at least one logical block in the netlist maps to).
* As an example:
* Having physical block types (EMPTY, LAB, DSP, IO),
* agent block types would be (LAB,IO) if netlist doesn't contain DSP blocks.
* Key : physical (agent) block type index
* Value : agent (physical) block type index
*/
std::unordered_map<int, int> phys_blk_type_to_agent_blk_type_map;
std::unordered_map<int, int> agent_blk_type_to_phys_blk_type_map;
};

/**
Expand Down
15 changes: 15 additions & 0 deletions vpr/src/base/vpr_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,18 @@ enum e_agent_algorithm {
SOFTMAX
};

/**
* @brief Used to determines the dimensionality of the RL agent exploration space
*
* Agent exploration space can be either based on only move types or
* can be based on (block_type, move_type) pair.
*
*/
enum e_agent_space {
MOVE_TYPE,
MOVE_BLOCK_TYPE
};

///@brief Used to calculate the inner placer loop's block swapping limit move_lim.
enum e_place_effort_scaling {
CIRCUIT, ///<Effort scales based on circuit size only
Expand Down Expand Up @@ -1065,6 +1077,8 @@ enum class e_place_delta_delay_algorithm {
* @param place_constraint_subtile
* True if subtiles should be specified when printing floorplan
* constraints. False if not.
*
*
*/
struct t_placer_opts {
t_place_algorithm place_algorithm;
Expand Down Expand Up @@ -1113,6 +1127,7 @@ struct t_placer_opts {
float place_agent_epsilon;
float place_agent_gamma;
float place_dm_rlim;
e_agent_space place_agent_space;
//int place_timing_cost_func;
std::string place_reward_fun;
float place_crit_limit;
Expand Down
3 changes: 2 additions & 1 deletion vpr/src/draw/manual_moves.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ e_create_move manual_move_display_and_propose(ManualMoveGenerator& manual_move_g
draw_manual_moves_window("");
update_screen(ScreenUpdatePriority::MAJOR, " ", PLACEMENT, nullptr);
move_type = e_move_type::MANUAL_MOVE;
return manual_move_generator.propose_move(blocks_affected, move_type, rlim, placer_opts, criticalities);
t_logical_block_type blk_type; //no need to specify block type in manual move "propose_move" function
return manual_move_generator.propose_move(blocks_affected, move_type, blk_type, rlim, placer_opts, criticalities);
}

#endif /*NO_GRAPHICS*/
109 changes: 66 additions & 43 deletions vpr/src/place/RL_agent_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,63 +23,68 @@ void create_move_generators(std::unique_ptr<MoveGenerator>& move_generator, std:
move_generator2 = std::make_unique<StaticMoveGenerator>(placer_opts.place_static_notiming_move_prob);
}
} else { //RL based placement
/* For the non timing driven placecment: the agent has a single state *
* - Available actions are (Uniform / Median / Centroid) *
/* For the non timing driven placement: the agent has a single state *
* - Available moves are (Uniform / Median / Centroid) *
* *
* For the timing driven placement: the agent has two states *
* - 1st state: includes 4 actions (Uniform / Median / Centroid / *
* - 1st state: includes 4 moves (Uniform / Median / Centroid / *
* WeightedCentroid) *
* - 2nd state: includes 7 actions (Uniform / Median / Centroid / *
* If agent should propose block type as well as the mentioned *
* move types, 1st state Q-table size is: *
* 4 move types * number of block types in the netlist *
* if not, the Q-table size is : 4 *
* *
* *
* - 2nd state: includes 7 moves (Uniform / Median / Centroid / *
* WeightedCentroid / WeightedMedian / Feasible *
* Region / CriticalUniform) *
* *
* This state is activated late in the anneale and in the Quench */
* 2nd state agent Q-table size is always 7 and always proposes *
* only move type. *
* This state is activated late in the anneal and in the Quench */

//extract available physical block types in the netlist
determine_agent_block_types();

auto& place_ctx = g_vpr_ctx.placement();
int num_1st_state_avail_moves = placer_opts.place_algorithm.is_timing_driven() ? NUM_PL_1ST_STATE_MOVE_TYPES : NUM_PL_NONTIMING_MOVE_TYPES;
int num_2nd_state_avail_moves = placer_opts.place_algorithm.is_timing_driven() ? NUM_PL_MOVE_TYPES : NUM_PL_NONTIMING_MOVE_TYPES;

if (placer_opts.place_agent_algorithm == E_GREEDY) {
VTR_LOG("Using simple RL 'Epsilon Greedy agent' for choosing move types\n");
std::unique_ptr<EpsilonGreedyAgent> karmed_bandit_agent1, karmed_bandit_agent2;
if (placer_opts.place_algorithm.is_timing_driven()) {
//agent's 1st state
karmed_bandit_agent1 = std::make_unique<EpsilonGreedyAgent>(NUM_PL_1ST_STATE_MOVE_TYPES, placer_opts.place_agent_epsilon);
karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent1);
//agent's 2nd state
karmed_bandit_agent2 = std::make_unique<EpsilonGreedyAgent>(NUM_PL_MOVE_TYPES, placer_opts.place_agent_epsilon);
karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator2 = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent2);
//agent's 1st state
if (placer_opts.place_agent_space == e_agent_space::MOVE_BLOCK_TYPE) {
VTR_LOG("Using simple RL 'Epsilon Greedy agent' for choosing move and block types\n");
karmed_bandit_agent1 = std::make_unique<EpsilonGreedyAgent>(num_1st_state_avail_moves,
place_ctx.agent_blk_type_to_phys_blk_type_map.size(),
placer_opts.place_agent_epsilon);
} else {
//agent's 1st state
karmed_bandit_agent1 = std::make_unique<EpsilonGreedyAgent>(NUM_PL_NONTIMING_MOVE_TYPES, placer_opts.place_agent_epsilon);
karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent1);
//agent's 2nd state
karmed_bandit_agent2 = std::make_unique<EpsilonGreedyAgent>(NUM_PL_NONTIMING_MOVE_TYPES, placer_opts.place_agent_epsilon);
karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator2 = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent2);
VTR_LOG("Using simple RL 'Epsilon Greedy agent' for choosing move types\n");
karmed_bandit_agent1 = std::make_unique<EpsilonGreedyAgent>(num_1st_state_avail_moves,
placer_opts.place_agent_epsilon);
}
karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent1);
//agent's 2nd state
karmed_bandit_agent2 = std::make_unique<EpsilonGreedyAgent>(num_2nd_state_avail_moves, placer_opts.place_agent_epsilon);
karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator2 = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent2);
} else {
VTR_LOG("Using simple RL 'Softmax agent' for choosing move types\n");
std::unique_ptr<SoftmaxAgent> karmed_bandit_agent1, karmed_bandit_agent2;

if (placer_opts.place_algorithm.is_timing_driven()) {
//agent's 1st state
karmed_bandit_agent1 = std::make_unique<SoftmaxAgent>(NUM_PL_1ST_STATE_MOVE_TYPES);
karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent1);
//agent's 2nd state
karmed_bandit_agent2 = std::make_unique<SoftmaxAgent>(NUM_PL_MOVE_TYPES);
karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator2 = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent2);
//agent's 1st state
if (placer_opts.place_agent_space == e_agent_space::MOVE_BLOCK_TYPE) {
VTR_LOG("Using simple RL 'Softmax agent' for choosing move and block types\n");
karmed_bandit_agent1 = std::make_unique<SoftmaxAgent>(num_1st_state_avail_moves,
place_ctx.agent_blk_type_to_phys_blk_type_map.size());
} else {
//agent's 1st state
karmed_bandit_agent1 = std::make_unique<SoftmaxAgent>(NUM_PL_NONTIMING_MOVE_TYPES);
karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent1);
//agent's 2nd state
karmed_bandit_agent2 = std::make_unique<SoftmaxAgent>(NUM_PL_NONTIMING_MOVE_TYPES);
karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator2 = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent2);
VTR_LOG("Using simple RL 'Softmax agent' for choosing move types\n");
karmed_bandit_agent1 = std::make_unique<SoftmaxAgent>(num_1st_state_avail_moves);
}
karmed_bandit_agent1->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent1);
//agent's 2nd state
karmed_bandit_agent2 = std::make_unique<SoftmaxAgent>(num_2nd_state_avail_moves);
karmed_bandit_agent2->set_step(placer_opts.place_agent_gamma, move_lim);
move_generator2 = std::make_unique<SimpleRLMoveGenerator>(karmed_bandit_agent2);
}
}
}
Expand Down Expand Up @@ -111,3 +116,21 @@ void update_move_generator(std::unique_ptr<MoveGenerator>& move_generator, std::
move_generator2 = std::move(current_move_generator);
}
}

void determine_agent_block_types() {
//Loop through all available logical block types and store the ones that exist in the netlist
auto& device_ctx = g_vpr_ctx.device();
auto& cluster_ctx = g_vpr_ctx.clustering();
auto& place_ctx = g_vpr_ctx.mutable_placement();
int agent_type_index = 0;
for (auto itype : device_ctx.logical_block_types) {
if (itype.index == 0) //ignore empty type
continue;
auto blk_per_type = cluster_ctx.clb_nlist.blocks_per_type(itype);
if (blk_per_type.size() != 0) {
place_ctx.phys_blk_type_to_agent_blk_type_map.insert(std::pair<int, int>(agent_type_index, itype.index));
place_ctx.agent_blk_type_to_phys_blk_type_map.insert(std::pair<int, int>(itype.index, agent_type_index));
agent_type_index++;
}
}
}
6 changes: 6 additions & 0 deletions vpr/src/place/RL_agent_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,10 @@ void assign_current_move_generator(std::unique_ptr<MoveGenerator>& move_generato
* @ brief move the updated current_move_generator to its original move_Generator structure based on he placer_options and the agent state
*/
void update_move_generator(std::unique_ptr<MoveGenerator>& move_generator, std::unique_ptr<MoveGenerator>& move_generator2, e_agent_state agent_state, const t_placer_opts& placer_opts, bool in_quench, std::unique_ptr<MoveGenerator>& current_move_generator);

/**
* @ brief determine which block types used by the netlist and create a map between physical block types and agent block types (the ones that are used in the netlist)
*/
void determine_agent_block_types();

#endif
Loading

0 comments on commit 0b42593

Please sign in to comment.