Creating and managing lines
This training page gives an overview of workflows using IP Lines.
Creating and managing lines
Some design teams work on a branch based development model. This model uses at least two branches - a stable or 'release' branch, and a development branch. Development branches are assumed to be inherently unstable, where users add new code or features. These features are then tested and merged onto a release branch for use in further downstream workflows. DM level branches are managed and traced in Perforce IPLM using 'Lines'. Line is a Perforce IPLM term for an IP branch. A line contains IP design files and all the other meta-data associated with an IP. See the IP Lines (Branches) page in the User Guide for more information.
Multiple lines for development
Following is an example of a branch/release flow for an IP (say lib.IP). The development of the IP happens on TRUNK, while stable releases can be delivered on a separate line, say 'rel1'. Any downstream flows like synthesis, layout, power, verification, etc can use the 'rel1' line to base their work. The advantage of this workflow is that designers can continue working on TRUNK and adding new features, while downstream flows have their own line to use. They can make modifications to the rel1 line if they want to perform some experiments of their own, without disturbing or picking up unstable changes from TRUNK.
Periodically, changes from TRUNK can be integrated into the 'rel1' line. This is done as follows
- Create a new release on TRUNK using the 'pi release' command. This release incorporates the latest changes on TRUNK. These releases on TRUNK are entirely in the developer's control, and can be made when the appropriate feature is ready or bug is fixed etc.
- Integrate the changes from TRUNK to 'rel1' using standard 'p4 integrate' command
- Create a new release on 'rel1' using 'pi release' command.
In addition, users can also make releases on either 'rel1' or TRUNK at any time for specific reasons like timing adjustments or feature updates.
Depot organization
In order to achieve this workflow, it is useful to organize P4 depots correctly. A typical depot organization has the following path
// <PREFIX> / <PROJECT|GLOBAL> / <IPNAME> / <BRANCH> /
For example, lines of IP1 in project 'tutorial' can have the following mdx_test locations:
//mdx_test/tutorial/ip/trunk
//mdx_test/tutorial/ip/rel1
Using the stable release line
In the above example, downstream flows should only pick releases from the 'rel1' line of the IP to ensure that they receive stable, verified releases. This can be achieved by creating a container IP 'tutorial.top' that includes the 'rel1' branch, a stable line, of the timers IP. This container can then be used by other teams as needed.
Note that the repo paths of 'tutorial.timers' is pointing to the 'rel1' portions of the repo within its IP path.
The block below:
- Creates the new line 'rel1' from the latest 'tutorial.timers'
- Creates the new container IP 'tutorial.top', setting 'rel1' as its resource
- Displays the newly created 'tutorial.top' tree
- Lists the 'rel1' line in verbose mode
> pi ip copy --repo-path //mdx_test/tutorial/timers/rel1 tutorial.timers@1.TRUNK tutorial.timers@.rel1 -d "New Release line"Successfully created new Line tutorial.timers@1.rel1
> pi ip add tutorial.top
<EDITOR WINDOW>...
# DM type is required
# One of: CONT FS P4
dm_type = CONT
...
# Resources are optional
# One resource per line (newlines require a leading space)
resources = tutorial.timers@1.rel1
...
<END EDITOR WINDOW>Successfully created IPV 'tutorial.top@0.TRUNK'.
> pi ip tree tutorial.top
tutorial.top@0.TRUNK
└─ tutorial.timers@0.rel1
└─ tutorial.gen_dig@1.rel1
> pi ip list tutorial.timers@.rel1 -v
IP Version tutorial.timers@1.rel1:
Description - timers
DM type - Perforce
Host -
Repo Path - //mdx_test/tutorial/timers/rel1
Source - tutorial.timers@1.TRUNK
Resources - tutorial.gen_dig@1.TRUNK
Current Aliases - HEAD LATEST
Historic Aliases -
Version Message - New Release line
IP created on - 2017-06-29 11:36:45 -0700 PDT by mdxtut
Line created on - 2017-07-03 11:43:09 -0700 PDT by admin
IP Version created on - 2017-07-03 11:43:09 -0700 PDT by admin
Project Properties:
* - --path $IP
IP Properties:
target_power - mW
target_size - sq-mm
IP Version Properties:
coverage - %
power - mW
power2 - mW
regr - /2000
size - sq-mm
Permissions on IP:
Owner - u:mdxtut
Write Permissions - u:mdxtut
Read Permissions - u:mdxtut
Permissions on Line rel1:
Owner - u:mdxtut
Write Permissions - u:mdxtut
Read Permissions - u:mdxtut
Hooks:
No Hooks defined.
Found 1 matching object(s)
Using containers for functions
Perforce IPLM containers are a great way to enable different teams and workflows. For example, a container that uses all its constituent IPs @HEAD on TRUNK line (lib.ip1@HEAD.TRUNK) can be used for development. Another container that uses the same IP on a fixed release on the 'rel1' line (lib.ip1@10.rel1) can be used by a downstream workflow like synthesis. An example project is shown below. This project has three top level container IPs:
- 'tutorial.top_devel': This top level container contains some key resources at HEAD.TRUNK (on the HEAD alias version and on the TRUNK line). This container is used by developers because they can get the latest changes on all the code on all the constituent IPs. Some other resources, like the 'env' IP are a fixed version to ensure that developers have a stable environment. Containers can use any mix of fixed and dynamic IPs as needed.
- 'tutorial.top_verif': This top level container contains some key resources on a moving alias 'VERIF_READY'. These aliases are put on specific releases by IP owners to allow the verification team to pick up a version of the IP ready to be tested.
- 'tutorial.top_synth': This top level container contains some key resources on the 'rel1' line at fixed versions. The 'rel1' line is created by the IP owners to allow slower moving workflows like synthesis to pick a stable version, and also to make minor modifications as they run through their flows. These modifications are on the 'rel1' line of the IP, so they don't impact the development. Similarly, new changes on the development line (TRUNK) do no impact on the synthesis team as they take days and weeks to finish their jobs.
IP tutorial.top_devel@2.TRUNK (LATEST): Description - This container can be used for development DM type - Container Resources - tutorial.timers@HEAD.TRUNK tutorial.trc@HEAD.TRUNK Current Aliases - HEAD LATEST Historic Aliases - Version Message - Container for development IP created on - 2017-05-15 13:20:06 -0700 PDT by admin Line created on - 2017-05-15 14:12:25 -0700 PDT by admin IP Version created on - 2017-05-15 14:12:25 -0700 PDT by admin IP tutorial.top_verif@1.TRUNK (LATEST): Description - This container can be used by Verification DM type - Container Resources - tutorial.timers@VERIF_READY.TRUNK tutorial.trc@VERIF_READY.TRUNK Current Aliases - HEAD LATEST Historic Aliases - Version Message - Container for verification IP created on - 2017-05-15 13:22:14 -0700 PDT by admin Line created on - 2017-05-15 14:20:55 -0700 PDT by admin IP Version created on - 2017-05-15 14:20:55 -0700 PDT by admin IP tutorial.top_synth@1.TRUNK (LATEST): Description - This container can be used by Synthesis team DM type - Container Resources - tutorial.timers@HEAD.rel1 tutorial.trc@HEAD.rel1 Current Aliases - HEAD LATEST Historic Aliases - Version Message - Container for releases IP created on - 2017-05-15 13:27:22 -0700 PDT by admin Line created on - 2017-05-15 14:30:34 -0700 PDT by admin IP Version created on - 2017-05-15 14:30:34 -0700 PDT by admin
Creating a new line in Perforce IPLM
Creating a new line in Perforce IPLM does not include branching the underlying DM system like P4. This requires customers to write their own DM branching routine (P4 'integrate' for example). The below script can be used as a highly functional starting point to help with this. The script below is self contained and works out of the box, but it can be modified to suit your needs.
This script performs the following steps:
- Create a workspace with the source IP on the release specified (LATEST release if not specified)
- Update the source client to include the branch location
- Create a P4 label of the files in the workspace
- Integrate the label from source to branch location
- Run the 'pi ip copy' command to create the same branch in PI
- Clean up the workspace, label etc.
#!/usr/bin/perl # -*- coding: utf-8 -*- ################################################################################ # Copyright (c) 2010-2016 Perforce, Inc. # All Rights Reserved. # # This source file is confidential and the proprietary information of # Perforce, Inc. and its receipt or possession does not convey any rights to # reproduce or disclose its contents, or to manufacture, use or sell anything # it may describe. Reproduction, disclosure or use without Perforce, Inc. # specific written authorization is strictly forbidden. ############################################################################### use strict; use warnings; sub print_help { print "This script creates a workspace with the specified IPV\n"; print "and then creates a new line of the IP by first copying\n"; print "P4 files over to that location and then branching PI\n"; print " Usage: $0 LIB.IP[\@VER.LINE] BRANCH_NAME P4_TARGET_PATH SCRATCH_WS_PATH [-n]\n"; print " Specifying '-n' at the end will show a dry-run of all the commands this script will run\n"; } sub get_client_details { my $spec = shift; my $name = $1 if ($spec =~ /^Client:\s+(.*)$/m); my $src_path = $1 if($spec =~ /\s+(\/\/\S+)\s/); return $name, $src_path; } sub run_cmd { my $cmd = shift; print $cmd."\n"; if (not $main::dry_run) { my $res = `$cmd 2>&1`; if ($?) { print $res; exit 1; } print $res if ($main::debug); return $res; } } if ((@ARGV != 4) && (@ARGV != 5)) { print_help(); exit 1; } our $debug = 0; our $dry_run = 0; my $libip; ######### ### Basic ARG Parse my $ip_name = $ARGV[0]; if ($ip_name =~ /\@/) { $libip = $`; } else { $libip = $ip_name; $ip_name .= "\@LATEST.TRUNK"; } my $branch_name = $ARGV[1]; my $target_base; my $target_path = $ARGV[2]; if ($target_path =~ /\/\.\.\.$/) { $target_base = $`; } else { $target_base = $target_path; $target_path .= "/..."; } my $scratch_dir = $ARGV[3]; if (@ARGV == 5) { $dry_run = 1;} my $cmd; my $res; ######### ## Create a workspace with IP in local mode if (!-e $scratch_dir) { $cmd = "mkdir -p $scratch_dir"; run_cmd($cmd); die ("Could not create scratch_dir $scratch_dir") if (!-e $scratch_dir); } chdir($scratch_dir); $cmd = "pi ip load $ip_name --local $libip"; run_cmd($cmd); chdir($libip); my $pwd = `pwd`; chomp $pwd; my $p4 = "p4 -d $pwd "; ######### ### Get the current $p4 client spec my $client_name = "TBD"; my $src_path = "..."; $cmd = "$p4 client -o"; my $p4_client_spec = run_cmd($cmd); ($client_name, $src_path) = get_client_details($p4_client_spec); ######### ## Update the existing client with a new line to the destination ## of the copy my $new_view_line = "\t$target_path //$client_name/".$libip.".".$branch_name."/...\n"; my $new_client_spec = $p4_client_spec; $new_client_spec .= $new_view_line; my $rnd = int(rand(10000)); my $file = "/tmp/pi_p4_copy_$rnd"; open(FH, ">", $file) || die ("Could not open file $file"); print FH $new_client_spec; close FH; $cmd = "$p4 client -i < $file"; run_cmd($cmd); ######### ## Create a label to reflect the current state of the WS open(FH, ">", $file) || die ("Could not open file $file"); my $label_spec = "pi_${libip}_${branch_name}"; print FH "Label:\t$label_spec\nView:\n\t$src_path\n"; close FH; $cmd = "$p4 label -i < $file"; run_cmd($cmd); $cmd = "$p4 labelsync -l $label_spec"; run_cmd($cmd); ######### ## Integrate across the branch using the label just created ## Submit the changes $cmd = "$p4 integrate $src_path\@$label_spec $target_path"; run_cmd($cmd); $cmd = "$p4 submit -d 'Integrating Branch $label_spec'"; run_cmd($cmd); ######### ## Make a branch in PI with the target $cmd = "pi ip copy $ip_name $libip\@.$branch_name --repo-path=$target_base"; run_cmd($cmd); $cmd = "pi ip list $libip\@.$branch_name"; my $ls = run_cmd($cmd); print $ls; ########################## ## Cleanup ## Update the client spec back to where it was, sync the workspace etc. open(FH, ">", $file) || die ("Could not open file $file"); print FH $p4_client_spec; close FH; $cmd = "$p4 client -i < $file"; run_cmd($cmd); $cmd = "$p4 sync ..."; run_cmd($cmd); $cmd = "$p4 label -d $label_spec"; run_cmd($cmd); $cmd = "rm $file"; run_cmd($cmd);